import logging, os, os.path
log = logging.getLogger(os.path.basename(__file__))


import memcache
mc  = memcache.Client(['127.0.0.1:11211'])
mdb = memcache.Client(['127.0.0.1:21201'])

import time

def get(key, version=None):
    return _get(mdb, key, version=version)

def set(key, foo):
    return _set(mdb, key, foo)


def mc_get(key, version=None):
    return _get(mc, key, version=version)

def mc_set(key, foo):
    return _set(mc, key, foo)


def _get(mdb, key, version=None):
    t0 = time.time()
    key = str(key)
    vkey = key+'.version'
    if version is None:
        ver = mdb.get(vkey)
        if ver is None:
            mdb.add(vkey, "0")
            ver = mdb.get(vkey)
    else:
        ver = str(version)
    content = mdb.get('%s.%s' % (key, ver))
    td = (time.time()-t0)*1000
    if td > 3:
        log.debug('get %r %3ims' % (key, td))
    return ver, content


def _set(mdb, key, foo):
    t0 = time.time()
    key = str(key)
    vkey = key+'.version'
    for i in range(9):
        ver = mdb.get(vkey)
        if ver is None:
            mdb.add(vkey, "0")
            ver = mdb.get(vkey)
        content = mdb.get('%s.%s' % (key, ver))
        if content is None:
            log.error('version %r is empty in memcached' % (ver, ))

        my_ver = int(ver or 0)+1
        my_content = foo(content)
        if not mdb.add('%s.%s' % (key, my_ver), my_content):
            if i == 7:
                mdb.delete('%s.%s' % (key, my_ver))
                log.error('%r: Deleting one version %r from memcached!' % (key, ver,))
            continue
        ver = mdb.incr(vkey)
        if ver != my_ver:
            raise Exception('memcache version exception %r %r' % (ver, my_ver))
        break
    else:
        raise Exception('memcache optimistic locking exception. Is memcache running?')
    td = (time.time()-t0)*1000
    if td > 3:
        log.debug('set %r %3ims' % (key, td))
    return my_ver, my_content


def output_get(key):
    return mc.get('%s.output' % (key,)) or ''

def output_set(key, value):
    return mc.set('%s.output' % (key,), value)
